﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using System.Xml;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using UFIDA.U9.WSS.ProxyService.Exceptions;
using UFIDA.U9.WSS.ProxyService.Json;
using UFSoft.UBF.Util.Log;

namespace UFIDA.U9.WSS.ProxyService.Behavior.WebHttp.Base
{
    public abstract class NewtonsoftJsonDispatchFormatter : IDispatchMessageFormatter
    {
        protected static readonly ILogger Logger = LoggerManager.GetLogger("NewtonsoftJsonDispatchFormatter");
        protected readonly OperationDescription _operation;
       

        protected NewtonsoftJsonDispatchFormatter(OperationDescription operation)
        {
            _operation = operation;
        }

        public void DeserializeRequest(Message message, object[] parameters)
        {
            byte[] rawBody = GetMessageRawBody(message);
            //解析参数
            ParseParameters(rawBody, parameters);
        }

        public Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result)
        {
            IContractResolver resolver = GetSerializeReplyContractResolver();
            byte[] body = JsonHelper.GetReturnJsonBody(result, resolver);
            Message replyMessage = Message.CreateMessage(messageVersion, _operation.Messages[1].Action,
                new RawBodyWriter(body));
            replyMessage.Properties.Add(WebBodyFormatMessageProperty.Name,
                new WebBodyFormatMessageProperty(WebContentFormat.Raw));
            HttpResponseMessageProperty respProp = new HttpResponseMessageProperty();
            respProp.Headers[HttpResponseHeader.ContentType] = "application/json;charset=utf-8";
            replyMessage.Properties.Add(HttpResponseMessageProperty.Name, respProp);
            return replyMessage;
        }

        /// <summary>
        ///     获取Message Raw Body
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        private static byte[] GetMessageRawBody(Message message)
        {
            object bodyFormatProperty;
            if (!message.Properties.TryGetValue(WebBodyFormatMessageProperty.Name, out bodyFormatProperty) ||
                (bodyFormatProperty as WebBodyFormatMessageProperty).Format != WebContentFormat.Raw)
            {
                throw new WSException(ExceptionCodes.ServiceRequestBodyFormatException,
                    "incoming messages must have a body format of Raw. Is a ContentTypeMapper set on the WebHttpBinding?");
            }

            using (XmlDictionaryReader bodyReader = message.GetReaderAtBodyContents())
            {
                bodyReader.ReadStartElement("Binary");
                return bodyReader.ReadContentAsBase64();
            }
        }

        /// <summary>
        ///     解析参数
        /// </summary>
        /// <param name="rawBody"></param>
        /// <param name="parameters"></param>
        protected abstract void ParseParameters(byte[] rawBody, object[] parameters);
        

        /// <summary>
        ///     获取回复的ContractResolver
        /// </summary>
        /// <returns></returns>
        protected abstract IContractResolver GetSerializeReplyContractResolver();
    }
}